#include <stdio.h>
#include <pthread.h>
#include <unistd.h>

// 1. 定义模型核心组件
#define BUF_SIZE 5  // 缓冲区大小
int buffer[BUF_SIZE];  // 中间缓冲区（存储数据）
int count = 0;         // 缓冲区中当前数据个数（0=空，BUF_SIZE=满）

pthread_mutex_t mutex;                // 互斥锁：保护缓冲区操作
pthread_cond_t cond_not_full;         // 条件变量：通知“缓冲区非满”（生产者等）
pthread_cond_t cond_not_empty;       // 条件变量：通知“缓冲区非空”（消费者等）

// 2. 生产者线程：生成1-10的数字，放入缓冲区
void* producer(void* arg) {
    int data;
    for (data = 1; data <= 10; data++) {  // 生产10个数据后退出
        // 加锁：操作缓冲区前必须先获取互斥锁
        pthread_mutex_lock(&mutex);

        // 若缓冲区满，等待“消费者取数据”（释放锁，阻塞等待）
        while (count == BUF_SIZE) {
            printf("生产者：缓冲区满，等待...\n");
            // 等待时会释放mutex，被唤醒后重新获取mutex
            pthread_cond_wait(&cond_not_full, &mutex);
        }

        // 放入数据到缓冲区（此时已持有锁，安全）
        buffer[count] = data;
        count++;
        printf("生产者：生产数据 %d，缓冲区剩余空间：%d\n", data, BUF_SIZE - count);

        // 解锁前，唤醒消费者（告知“缓冲区非空，可以取数据了”）
        pthread_cond_signal(&cond_not_empty);
        pthread_mutex_unlock(&mutex);

        sleep(1);  // 模拟生产耗时（比如读取文件、计算数据）
    }
    return NULL;
}

// 3. 消费者线程：从缓冲区取数据并处理
void* consumer(void* arg) {
    int data;
    while (1) {  // 循环消费（实际场景可加退出条件）
        // 加锁：操作缓冲区前必须先获取互斥锁
        pthread_mutex_lock(&mutex);

        // 若缓冲区空，等待“生产者放数据”（释放锁，阻塞等待）
        while (count == 0) {
            printf("消费者：缓冲区空，等待...\n");
            pthread_cond_wait(&cond_not_empty, &mutex);
        }

        // 从缓冲区取数据（此时已持有锁，安全）
        count--;
        data = buffer[count];  // 从末尾取（简化逻辑）
        printf("消费者：消费数据 %d，缓冲区剩余数据：%d\n", data, count);

        // 解锁前，唤醒生产者（告知“缓冲区非满，可以放数据了”）
        pthread_cond_signal(&cond_not_full);
        pthread_mutex_unlock(&mutex);

        sleep(2);  // 模拟消费耗时（比如处理数据、写入数据库）
    }
    return NULL;
}

int main() {
    pthread_t prod_tid, cons_tid;

    // 初始化互斥锁和条件变量
    pthread_mutex_init(&mutex, NULL);
    pthread_cond_init(&cond_not_full, NULL);
    pthread_cond_init(&cond_not_empty, NULL);

    // 创建生产者和消费者线程
    pthread_create(&prod_tid, NULL, producer, NULL);
    pthread_create(&cons_tid, NULL, consumer, NULL);

    // 等待线程结束（生产者生产10个数据后退出，消费者可手动终止）
    pthread_join(prod_tid, NULL);
    pthread_join(cons_tid, NULL);  // 实际运行时，可按Ctrl+C终止

    // 销毁资源
    pthread_mutex_destroy(&mutex);
    pthread_cond_destroy(&cond_not_full);
    pthread_cond_destroy(&cond_not_empty);

    return 0;
}
